﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace Algorithms
{
    public class RectHV
    {
        private readonly double _xmin, _ymin;   // minimum x- and y-coordinates
        private readonly double _xmax, _ymax;   // maximum x- and y-coordinates

        // construct the axis-aligned rectangle [xmin, xmax] x [ymin, ymax]
        public RectHV(double xmin, double ymin, double xmax, double ymax)
        {
            if (xmax < xmin || ymax < ymin)
            {
                throw new ArgumentException("Invalid rectangle");
            }
            this._xmin = xmin;
            this._ymin = ymin;
            this._xmax = xmax;
            this._ymax = ymax;
        }

        // accessor methods for 4 coordinates
        public double xmin() { return _xmin; }
        public double ymin() { return _ymin; }
        public double xmax() { return _xmax; }
        public double ymax() { return _ymax; }

        // width and height of rectangle
        public double width() { return _xmax - _xmin; }
        public double height() { return _ymax - _ymin; }

        // does this axis-aligned rectangle intersect that one?
        public bool intersects(RectHV that)
        {
            return this._xmax >= that._xmin && this._ymax >= that._ymin
                && that._xmax >= this._xmin && that._ymax >= this._ymin;
        }

        // distance from p to closest point on this axis-aligned rectangle
        public double distanceTo(Point2D p)
        {
            return Math.Sqrt(this.distanceSquaredTo(p));
        }

        // distance squared from p to closest point on this axis-aligned rectangle
        public double distanceSquaredTo(Point2D p)
        {
            double dx = 0.0, dy = 0.0;
            if (p.x() < _xmin) dx = p.x() - _xmin;
            else if (p.x() > _xmax) dx = p.x() - _xmax;
            if (p.y() < _ymin) dy = p.y() - _ymin;
            else if (p.y() > _ymax) dy = p.y() - _ymax;
            return dx * dx + dy * dy;
        }

        // does this axis-aligned rectangle contain p?
        public bool contains(Point2D p)
        {
            return (p.x() >= _xmin) && (p.x() <= _xmax)
                && (p.y() >= _ymin) && (p.y() <= _ymax);
        }

        // are the two axis-aligned rectangles equal?
        public bool equals(Object y)
        {
            if (y == this) return true;
            if (y == null) return false;
           // if (y.getClass() != this.getClass()) return false;
            RectHV that = (RectHV)y;
            if (this._xmin != that._xmin) return false;
            if (this._ymin != that._ymin) return false;
            if (this._xmax != that._xmax) return false;
            if (this._ymax != that._ymax) return false;
            return true;
        }

        // return a string representation of this axis-aligned rectangle
        public String toString()
        {
            return "[" + _xmin + ", " + _xmax + "] x [" + _ymin + ", " + _ymax + "]";
        }

    }

}
